home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Messaging Service Access Module / Internet PMSAM / Internet PMSAM source / gatewayget.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-12  |  8.0 KB  |  328 lines  |  [TEXT/MPS ]

  1. /*-------------------------------------------------------------------
  2.  
  3. AOCE Post Office Protocol (POP) / Simple Mail Transfer Protocol (SMTP)
  4. Mail Service Access Module
  5.  
  6. written by Steve Falkenburg-- MacDTS
  7. ©1991-1993 Apple Computer, Inc.
  8.  
  9. --------------
  10. change history
  11. --------------
  12.  
  13. SJF        02/19/93    update for beta build    b1
  14. SJF        10/29/92    update to a11            a11
  15. SJF        06/08/92    update to a8            a8
  16. SJF        02/15/92    first working version    a4.5
  17. SJF        10/16/91    initial coding            a3
  18.  
  19. ---------------------------------------------------------------------*/
  20.  
  21. #ifndef  __OCE__
  22. #include <OCE.h>
  23. #endif
  24.  
  25. #ifndef __OCEMAIL__
  26. #include <OCEMail.h>
  27. #endif
  28.  
  29. #include "const.h"
  30. #include "gwerrors.h"
  31. #include "mytypes.h"
  32. #include "globals.h"
  33. #include "utils.h"
  34. #include "spoolsystem.h"
  35. #include "gatewaystuff.h"
  36. #include "authstuff.h"
  37. #include "errorhandling.h"
  38.  
  39. #include "spooltoexternal.h"
  40. #include "spoolfromaoce.h"
  41. #include "spooltoaoce.h"
  42. #include "reports.h"
  43.  
  44. #include "gatewayget.h"
  45.  
  46.  
  47. // PeriodicCheckGet
  48. //
  49. // when the toolbox thinks that it's time to check for mail, this function is called, in addition
  50. // to being called on startup of the gateway
  51. //
  52. OSErr PeriodicCheckGet(void)
  53. {
  54.     short slotIndex,arrIndex;
  55.     SlotSpec *slotSpec;
  56.     OSErr err = noErr;
  57.     unsigned long dateTime;
  58.     
  59.     TraceExecution("\pPeriodicCheckGet");
  60.  
  61.     GetDateTime(&dateTime);    
  62.  
  63.     for (slotIndex = arrIndex = 0; (err==noErr) && (slotIndex<gNumSlots); arrIndex++) {
  64.         if ((gLocation != 0) && (gSlotDatabase[arrIndex].locationActive & MailLocationMask(gLocation))
  65.                 && gSlotDatabase[arrIndex].enabled) {    // if the slot is in use, process it
  66.             slotIndex++;
  67.             slotSpec = &gSlotDatabase[arrIndex];
  68.             if (slotSpec->dirIdentity.valid) {
  69.                 EnterAuthCriticalSection();    // don't allow locking of local identity while we're here
  70.                 if (TimeToCheckGet(&slotSpec->stdInfo.sendReceiveTimer,slotSpec->lastCheckGet,dateTime)) {
  71.                     err = DoSlotGet(slotSpec);
  72.                     if (err==noErr)
  73.                         slotSpec->lastCheckGet = dateTime;
  74.                 }
  75.                 ExitAuthCriticalSection();
  76.             }
  77.         }
  78.         else slotIndex++;    // index past slots that are disabled
  79.     }
  80.     return err;
  81. }
  82.  
  83.  
  84. // TimeToCheckGet
  85. //
  86. // returns true if it's time to check for mail.  this function assumes the mailtimers are
  87. // in minutes, not seconds, since this seems to be what the toolbox is using for its scheduling
  88. // of eppcs.  note that the OCEMail.h header file specifies that these values are in seconds.
  89. //
  90. Boolean TimeToCheckGet(MailTimers *mailTimer,unsigned long lastCheck,unsigned long curTime)
  91. {
  92.     DateTimeRec dtRec;
  93.     unsigned long midnightSecs;    
  94.  
  95.     switch (mailTimer->sendTimeKind) {
  96.         case kMailTimerOff:
  97.             return false;                    // never check if there is no interval
  98.             break;
  99.         case kMailTimerFrequency:            // check if past frequency+lastCheck
  100.             if (mailTimer->send.frequency==0)
  101.                 return false;
  102.             return ((lastCheck + (60*mailTimer->send.frequency))<curTime);
  103.             break;
  104.         case kMailTimerTime:                // check at a specific time
  105.             if ((lastCheck + kOneDaySecs) > curTime)
  106.                 return false;
  107.             Secs2Date(curTime,&dtRec);    // get date of last midnight
  108.             dtRec.hour = 0;
  109.             dtRec.minute = 0;
  110.             dtRec.second = 0;
  111.             Date2Secs(&dtRec,&midnightSecs);
  112.             return ( (midnightSecs+(60*mailTimer->send.connectTime)) > curTime );
  113.             break;
  114.     }
  115.     return false;        
  116. }
  117.  
  118.  
  119. // DoSlotGet
  120. //
  121. // when we've determined that it's actually time to do a "get" (send to external system) this
  122. // function is called by PeriodicCheckGet.
  123. //
  124. OSErr DoSlotGet(SlotSpec *slot)
  125. {
  126.     OSErr err,enumErr,err2;
  127.     MSAMEnumeratePB gwp;
  128.     EnumOutQReply enumBlock;
  129.     long nextMsgSeq;
  130.     MailMsgRef msgRef;
  131.     FSSpec spoolSpec;
  132.     
  133.     TraceExecution("\pDoSlotGet");
  134.     
  135.     // first, we pull all the pending letters out of the AOCE slot and spool them
  136.     
  137.     nextMsgSeq = 1;
  138.     
  139.     err = noErr;
  140.     
  141.     do {
  142.         gwp.ioCompletion = (ProcPtr)MSAMCompletion;
  143.         gwp.queueRef  = slot->outQueue;
  144.         gwp.startSeqNum = nextMsgSeq;
  145.         gwp.buffer.bufferSize = sizeof(EnumOutQReply);
  146.         gwp.buffer.buffer = (Ptr)&enumBlock;
  147.         MSAMEnumerate((MSAMParam *)&gwp,true);
  148.         enumErr = WaitPBDone(&gwp);
  149.         nextMsgSeq = gwp.nextSeqNum;
  150.         if (enumErr==noErr && gwp.buffer.dataSize>sizeof(short) && (enumBlock.message.done==false)) {
  151.         
  152.             err = CreateSpoolFile(&spoolSpec);    // make our spool file
  153.             if (err!=noErr)
  154.                 break;
  155.             
  156.             // here, the message is spooled to the common data area, and then sent to the external gateway
  157.                         
  158.             err = GetSlotMessage(slot->outQueue,&enumBlock.message,&msgRef,&spoolSpec);
  159.             if (err==noErr) {
  160.                 err = SpoolToExternalGW(&spoolSpec,slot);
  161.                 err2 = DoneSlotMessage((err==noErr),slot->outQueue,&enumBlock.message,&spoolSpec,msgRef);
  162.                 if (err==noErr)
  163.                     err = err2;
  164.             }
  165.             
  166.             if (err!=noErr) {
  167.                 RemoveSpoolFile(&spoolSpec);
  168.                 break;
  169.             }
  170.                 
  171.             err = RemoveSpoolFile(&spoolSpec);
  172.             if (err!=noErr)
  173.                 break;
  174.         }
  175.     }
  176.     while (enumErr==noErr && nextMsgSeq!=0);
  177.     
  178.     // error retry mechanism- only report errors after we fail a number of times
  179.     // specified in kAllowedRetries
  180.     
  181.     err = RetrySlotError(err,slot,false);
  182.  
  183.     return err;
  184. }
  185.  
  186.  
  187. OSErr GetSlotMessage(MSAMQueueRef qid,MSAMEnumerateOutQReply *msg,MailMsgRef *retMsgRef,FSSpec *spoolSpec)
  188. {
  189.     OSErr err;
  190.     MSAMParam gwp;
  191.     MailMsgRef msgRef;
  192.     
  193.     // mark message as being sent
  194.     
  195.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
  196.     gwp.pmsamSetStatus.queueRef = qid;
  197.     gwp.pmsamSetStatus.seqNum = msg->seqNum;
  198.     gwp.pmsamSetStatus.msgHint = 0;
  199.     gwp.pmsamSetStatus.status = kPMSAMStatusSending;
  200.     err = PMSAMSetStatus(&gwp,true);
  201.     err = WaitPBDone(&gwp);
  202.     if (err!=noErr)
  203.         return err;
  204.  
  205.     // open message
  206.     
  207.     gwp.msamOpen.queueRef  = qid;                        
  208.     gwp.msamOpen.seqNum = msg->seqNum;
  209.     MSAMOpen(&gwp,true);
  210.     err = WaitPBDone(&gwp);
  211.     if (err!=noErr) {
  212.         return err;
  213.     }
  214.     msgRef = gwp.msamOpen.mailMsgRef;
  215.     
  216.     // put message into spool area
  217.     
  218.     err = SpoolFromAOCE(msgRef,spoolSpec);
  219.     if (err!=noErr) {
  220.         // might log this error with error reporting log
  221.         // close message
  222.         gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;                    
  223.         gwp.msamClose.mailMsgRef = msgRef;
  224.         MSAMClose(&gwp,true);    
  225.         WaitPBDone(&gwp);
  226.     }
  227.     
  228.     *retMsgRef = msgRef;
  229.     return err;
  230. }
  231.  
  232.  
  233. // we mark recipients, send delivery reports, close the message
  234. //
  235. // *** NOTE
  236. //
  237. // a14 and later note:  we no longer delete the outging messages from the queue
  238. // as per the "Public API deltas" document corresponding to the queue mgr redesign
  239. //
  240. // ********
  241.  
  242. OSErr DoneSlotMessage(Boolean sent,MSAMQueueRef qid,MSAMEnumerateOutQReply *msg,FSSpec *spoolSpec,MailMsgRef msgRef)
  243. {
  244.     MSAMParam gwp;
  245.     OSErr err;
  246.     unsigned long bufferLen;
  247.     short recipientIndex,spoolIndex;
  248.     
  249.     // send the recipient reports for all recipients
  250.     
  251.     err = GenerateDeliveryReport(sent,spoolSpec);
  252.     if (err!=noErr)
  253.         return err;
  254.         
  255.     // mark each recipient
  256.     
  257.     if (sent) {
  258.         for (spoolIndex=0,err=noErr; err==noErr; spoolIndex++) {
  259.             bufferLen = sizeof(short);
  260.             err = GetFromSpool(spoolSpec,kRecipientType,kReportCreator,spoolIndex,(Ptr)&recipientIndex,&bufferLen,0);
  261.             if ((err==noErr)||(err==kMoreData)) {
  262.                 err = MarkRead(msgRef,recipientIndex);
  263.                 if (err!=noErr)
  264.                     return err;
  265.             }
  266.         }
  267.     }
  268.     
  269.     // close message
  270.     
  271.     gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;                    
  272.     gwp.msamClose.mailMsgRef = msgRef;
  273.     MSAMClose(&gwp,true);    
  274.     err = WaitPBDone(&gwp);
  275.     if (err!=noErr)
  276.         return err;
  277.     
  278.     // change status to error if it didn't send
  279.     
  280.     if (!sent) {
  281.         gwp.header.ioCompletion = (ProcPtr)MSAMCompletion;
  282.         gwp.pmsamSetStatus.queueRef = qid;
  283.         gwp.pmsamSetStatus.seqNum = msg->seqNum;
  284.         gwp.pmsamSetStatus.msgHint = 0;
  285.         gwp.pmsamSetStatus.status = kPMSAMStatusError;
  286.         err = PMSAMSetStatus(&gwp,true);
  287.         err = WaitPBDone(&gwp);
  288.         if (err!=noErr)
  289.             return err;
  290.     }
  291.     
  292.     // mark that we sent message
  293.     
  294.     msg->done = true;
  295.     return err;                                
  296. }
  297.  
  298.  
  299.  
  300. OSErr MarkRead(MailMsgRef msgRef,short recipIndex)
  301. {
  302.     MSAMnMarkRecipientsPB gwp;
  303.     short markMsgs[2];
  304.     OSErr err;
  305.     
  306.     TraceExecution("\pMarkRead");
  307.     
  308.     markMsgs[0] = 1;                // count
  309.     markMsgs[1] = recipIndex;        // index to mark
  310.     
  311.     gwp.ioCompletion = (ProcPtr)MSAMCompletion;
  312.     gwp.mailMsgRef = msgRef;
  313.     gwp.buffer.buffer = (Ptr)markMsgs;
  314.     gwp.buffer.bufferSize = sizeof(short) + sizeof(short);
  315.  
  316.     MSAMnMarkRecipients((MSAMParam *)&gwp,true);
  317.     err = WaitPBDone(&gwp);
  318.     
  319. #ifdef kDEBUG
  320.     if (err==kOCEInvalidIndex) {
  321.         DebugStr("\pGot kOCEInvalidIndex");
  322.     }
  323. #endif
  324.     
  325.     return err;
  326. }
  327.  
  328.